#include "gitupdater.h"
#include <QDebug>
#include <QMetaObject>

gitUpdater::gitUpdater(QObject *parent) : QObject(parent), process(nullptr), timeoutTimer(nullptr), isCurrentVersion(false)
{
}

gitUpdater::~gitUpdater()
{
    if (process) delete process;
    if (timeoutTimer) delete timeoutTimer;
}

void gitUpdater::init()
{
    process = new QProcess(this);
    timeoutTimer = new QTimer(this);

    connect(process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
            this, &gitUpdater::handleProcessFinished);
    connect(process, &QProcess::readyReadStandardOutput,
            this, &gitUpdater::handleReadyReadStandardOutput);
    connect(process, &QProcess::readyReadStandardError,
            this, &gitUpdater::handleReadyReadStandardError);
    connect(process, &QProcess::errorOccurred,
            this, &gitUpdater::handleProcessError);

    connect(timeoutTimer, &QTimer::timeout, this, &gitUpdater::handleTimeout);
    timeoutTimer->setSingleShot(true);


    qInfo() << "gitUpdater initialized";
}

void gitUpdater::readProcessOutput()
{
    qDebug() << "Attempting to readProcessOutput:" ;

    QString output = process->readAll();
    qDebug() << "readProcessOutput:" << output;

}

void gitUpdater::getCurrentVersion()
{
    qDebug() << "Starting to get current version.";
    currentOperation = "describe";

    //runCommand("git", QStringList() << "describe" << "--tags" <<"--exact-match", 5000); // 5秒超时
    isCurrentVersion = true;
}

void gitUpdater::getLatestVersion()
{
    qDebug() << "Starting to get latest version.";
    currentOperation = "fetch -tags";
    runCommand("git", QStringList() << "pull", 5000);
    //runCommand("git", QStringList() << "fetch" << "--tags", 100000); // 10秒超时
    QTimer *readTimer = new QTimer(this);
    connect(readTimer, &QTimer::timeout, this, &gitUpdater::readProcessOutput);
    readTimer->start(100); // 每100毫秒检查一次输出
}

void gitUpdater::startUpdate()
{


    qDebug() << "Starting update.";
    currentOperation = "fetch";
    runCommand("git", QStringList() << "fetch" << "origin" << "master", 30000); // 30秒超时
}

void gitUpdater::handleProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
    timeoutTimer->stop();
    qDebug() << "Process finished with exit code:" << exitCode << "and exit status:" << exitStatus;

    if (exitStatus == QProcess::CrashExit) {
        qWarning() << "Process crashed.";
        QVariantMap result;
        result["error"] = "Process crashed";
        emit response(false, currentOperation, result);
        return;
    }
    QString output = lastOutput.trimmed();
    if(!finishWthSuccessful)
    {
        QVariantMap result;
        result["error"] = output;
        emit response(false, currentOperation, result);
        return;
    }
    lastOutput.clear();
    qDebug() << "Command output:" << output;

    if (process->program() == "git") {
        if (currentOperation == "describe") {
            qDebug() << "Parsing git describe output.";
            parseGitDescribeOutput(output, isCurrentVersion);
        } else if (currentOperation == "ls-remote") {
            qDebug() << "Parsing git ls-remote output.";
            parseGitLsRemoteOutput(output);
        } else if (currentOperation == "fetch") {
            qDebug() << "Starting git reset after fetch.";
            currentOperation = "reset";
            runCommand("git", QStringList() << "reset" << "--hard" << "origin/master", 10000); // 10秒超时
        } else if (currentOperation == "reset") {
            qDebug() << "Update process completed successfully.";
            QVariantMap result;
            result["message"] = "Update completed successfully";
            emit response(true, currentOperation, result);
        }else if(currentOperation == "fetch -tags")
        {
            currentOperation = "ls-remote";
            runCommand("git", QStringList() << "ls-remote" << "--tags" << "origin", 10000); // 10秒超时
            isCurrentVersion = false;
        } else if (currentOperation == "log") {
            qDebug() << "Parsing git log output.";
            QVariantMap result;
            result["details"] = output;
            if (isCurrentVersion) {
                result["version"] = last_version;
                emit response(true, "getCurrentVersion", result);
            } else {
                result["version"] = latestTag.trimmed();
                emit response(true, "getLatestVersion", result);
            }
        }
    }
}

void gitUpdater::handleProcessError(QProcess::ProcessError error)
{
    timeoutTimer->stop();
    qWarning() << "Process error occurred:" << process->errorString();
    QVariantMap result;
    result["error"] = process->errorString();
    emit response(false, currentOperation, result);

}

void gitUpdater::handleReadyReadStandardOutput()
{
    lastOutput += process->readAllStandardOutput();
    qDebug() << "Standard Output:" << lastOutput;
    finishWthSuccessful=true;
}

void gitUpdater::handleReadyReadStandardError()
{
    lastOutput += process->readAllStandardError();
    qDebug() << "Standard Error:" << lastOutput;
    finishWthSuccessful=false;
}

void gitUpdater::handleTimeout()
{
    qWarning() << "Process timed out.";
    process->kill();
    QVariantMap result;
    result["error"] = "Process timed out";
    emit response(false, currentOperation, result);
}

void gitUpdater::runCommand(const QString &program, const QStringList &arguments, int timeout)
{
    qDebug() << "Running command:" << program << arguments << "with timeout:" << timeout;
    process->setWorkingDirectory(appRootPath);
    process->setProcessChannelMode(QProcess::MergedChannels); // 合并标准输出和错误输出
    process->start(program, arguments);
    timeoutTimer->start(timeout);
}

void gitUpdater::parseGitDescribeOutput(const QString &output, bool isCurrent)
{
    qDebug() << "Parsing git describe output.";
    QStringList lines = output.split("\n");
    if (!lines.isEmpty()) {
        last_version = lines.first().trimmed();
        currentOperation = "log";
        //runCommand("git", QStringList() << "for-each-re" << "-1" << "--pretty=%B" << version, 5000); // 5秒超时
        runCommand("git", QStringList()
                              << "for-each-ref"
                              << "refs/tags/" + last_version
                              << "--format='%(contents)'", 5000); // 5秒超时
    } else {
        qWarning() << "No output from git describe.";
        QVariantMap result;
        result["error"] = "No output from git describe";
        emit response(false, currentOperation, result);
    }
}

void gitUpdater::parseGitLsRemoteOutput(const QString &output)
{
    qDebug() << "Parsing git ls-remote output.";
    QStringList lines = output.split("\n");
    if (lines.size()>1) {
        latestTag = lines[lines.size()-2].split("\t").last().split("/").last().trimmed();
        parseGitDescribeOutput(latestTag, false);
    } else {
        qWarning() << "No tags found in git ls-remote output.";
        QVariantMap result;
        result["error"] = "No tags found";
        emit response(false, currentOperation, result);
    }
}
